package com.github.wui.TimerSelector

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Point
import android.graphics.Typeface
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup.LayoutParams
import androidx.core.text.isDigitsOnly
import com.github.wui.R

import java.util.Calendar


/**
 * 自定义时间选择器
 *
 * @author <a href="https://github.com/karai-oss">Mr.xie</a>
 * @Date 2025/4/26
 */

class TimerSelector : View {


    /**
     * 小时 模式 默认是24小时制度
     */
    private var hoursModel: Int = 0;


    private var space: Float = 10F;

    private lateinit var colonPaint: Paint


    private var colonColor = Color.BLACK;

    /**
     * 文本大小
     */
    private var fontSize: Float = 50f;


    /**
     * 选中时候的文字画笔
     */
    private lateinit var selectedPaint: Paint


    /**
     * 没有选中的文字画笔
     */
    private lateinit var unselectedPaint: Paint;


    /**
     * 选中的文字颜色
     */
    private var selectedColor = Color.WHITE


    /**
     * 未选中的文字颜色
     */
    private var unselectedColor = Color.parseColor("#e7e7e7")


    /**
     * 小时的位置集合
     */
    private var hoursPoints = mutableListOf<Point>()

    /**
     * 秒数的位置集合
     */
    private var millsPoint = mutableListOf<Point>()

    /**
     * 目前是谁滑动 是小时滑动 还是 秒数滑动 秒数 ： 1 小时 ： 0
     */
    private var model = 0;

    /**
     * 是否是第一次加载
     */
    private var isStart = true;


    private lateinit var linePaint: Paint;

    private var lineColor: Int = Color.WHITE


    // 选中区域大 宽和高
    var selection_w = 160;
    var selection_h = 140f;


    /**
     * 冒号的字体大小
     */
    private var colonSize = 80f

    /**
     * 外框线的宽度
     */
    private var lineWidth = 2f;


    /**
     * 线是否是圆头的
     */
    private var line_is_cap: Boolean = false;

    private var font_bold: Int = 100


    /**
     * 默认选中的小时
     */
    @JvmField
    var selectedNum: String = "12"

    /**
     * 默认选中的描述
     */
    @JvmField
    var selectedMills = "16"

    //************ 记录前一个时分 ********************** //
    var preSelectHours = selectedNum
    var preSelectMills = selectedMills


    /**
     * 用调节字体左右位子
     */
    private var offsetX: Float = 0F;


    /**
     * 指定每次可以滑动的距离
     */
    private var scrollDistance = 0F
    private var scrollDistanceValue = 0F


    private var leftCount = 24;
    private var rightCount = 60;

    private var isShowColon = true;


    private var timeScrollListener: ITimerScrollListener? = null;

    constructor(context: Context?) : super(context) {
        init(context, null);
    }


    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
        init(context, attrs)
    }

    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ) {
        init(context, attrs)
    }


    private fun init(context: Context?, attrs: AttributeSet?) {
        val calendar = Calendar.getInstance()
        val typedArray = context!!.obtainStyledAttributes(attrs, R.styleable.TimeSelector)
        lineColor = typedArray.getColor(R.styleable.TimeSelector_line_color, Color.WHITE)
        selectedColor = typedArray.getColor(R.styleable.TimeSelector_inner_text_color, Color.WHITE)
        unselectedColor =
            typedArray.getColor(R.styleable.TimeSelector_outer_text_color, Color.WHITE)
        colonColor = typedArray.getColor(R.styleable.TimeSelector_colon_color, Color.BLACK)
        selection_w =
            typedArray.getDimension(R.styleable.TimeSelector_selection_width, 160f).toInt()
        selection_h = typedArray.getDimension(R.styleable.TimeSelector_selection_height, 100f)
        space = typedArray.getDimension(R.styleable.TimeSelector_colon_space, 10f)
        fontSize = typedArray.getDimension(R.styleable.TimeSelector_font_size, 50f)
        colonSize = typedArray.getDimension(R.styleable.TimeSelector_colon_size, 80f)
        lineWidth = typedArray.getDimension(R.styleable.TimeSelector_line_width, 4f)
        offsetX = typedArray.getDimension(R.styleable.TimeSelector_offsetX, 0F)
        scrollDistanceValue = typedArray.getDimension(R.styleable.TimeSelector_scrollDistance, 10F)
        line_is_cap = typedArray.getBoolean(R.styleable.TimeSelector_line_is_cap, false)
        font_bold = typedArray.getInteger(R.styleable.TimeSelector_font_bold, 0)
        leftCount = typedArray.getInteger(R.styleable.TimeSelector_leftCount, 24)
        rightCount = typedArray.getInteger(R.styleable.TimeSelector_rightCount, 60)
        isShowColon = typedArray.getBoolean(R.styleable.TimeSelector_isShowColon, true)


        val default_hours = typedArray.getString(R.styleable.TimeSelector_default_hours)
        val default_mills = typedArray.getString(R.styleable.TimeSelector_default_mills)
        if (default_hours == null || default_hours == "") {
            selectedNum = calendar.get(Calendar.HOUR_OF_DAY).toString()
        } else {
            selectedNum = default_hours;
        }
        if (default_mills == null || default_mills == "") {
            selectedMills = calendar.get(Calendar.MINUTE).toString()
        } else {
            selectedMills = default_mills;
        }
        preSelectHours = selectedNum
        preSelectMills = selectedMills

        typedArray.recycle()
        initPaint()
        isStart = true;
    }


    @SuppressLint("ClickableViewAccessibility")
    private fun initListener() {
    }


    private fun initPaint() {

        linePaint = Paint();
        linePaint.color = lineColor;
        linePaint.strokeWidth = lineWidth;
        linePaint.isAntiAlias = true;
        if (line_is_cap) linePaint.strokeCap = Paint.Cap.ROUND else linePaint.strokeCap =
            Paint.Cap.SQUARE

        colonPaint = Paint();
        colonPaint.textSize = colonSize;
        colonPaint.isAntiAlias = true;
        colonPaint.color = colonColor


        // ============ 选中文字画笔 ============= //

        selectedPaint = Paint()
        selectedPaint.isAntiAlias = true
        selectedPaint.textSize = fontSize
        selectedPaint.color = selectedColor;
        selectedPaint.typeface = if (font_bold == 1) Typeface.create(
            Typeface.DEFAULT,
            Typeface.BOLD
        ) else Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)

        // ============ 未选中时候的文字画笔 ============== //

        unselectedPaint = Paint()
        unselectedPaint.isAntiAlias = true
        unselectedPaint.textSize = fontSize
        unselectedPaint.color = unselectedColor;
        unselectedPaint.typeface = if (font_bold == 1) Typeface.create(
            Typeface.DEFAULT,
            Typeface.BOLD
        ) else Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)

    }


    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        var width = MeasureSpec.getSize(widthMeasureSpec);
        var height = MeasureSpec.getSize(heightMeasureSpec);

        val widgetWidth = layoutParams.width
        val widgetHeight = layoutParams.height

        if (widgetWidth != LayoutParams.WRAP_CONTENT && widgetWidth != LayoutParams.MATCH_PARENT) {
            width = widgetWidth;
        }

        if (widgetHeight != LayoutParams.WRAP_CONTENT && widgetHeight != LayoutParams.MATCH_PARENT) {
            height = widgetHeight;
        }

        setMeasuredDimension(width, height)

    }


    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        // 冒号绘制的X Y
        val colonX = measuredWidth / 2f
        val colonY = measuredHeight / 2f + 30f
        // 绘制中间的冒号
        if (isShowColon) {
            drawColon(canvas, colonX, colonY)
        }
        drawSelectionLines(canvas, colonX, colonY);
        if (isStart) {
            initHoursPoint();
            initMillsPoint()
        }
        drawHoursAndMill(canvas);
    }

    private fun initMillsPoint() {
        millsPoint.clear()
        var topIndex = selectedMills.toInt()
        var bottomIndex = 1;
        var rightSelectionStartX =
            leftSelectionStartX + 2 * space + selection_w + selection_w / 2 + 30f //30f 是冒号的宽度
        var selectedHoursY =
            leftSelectionStartY + (selection_h / 2 + fontSize / 2 - 5)

        for (i in 0..rightCount) {
            if (i < selectedMills.toInt()) { // 上面的数字
                millsPoint.add(
                    Point(
                        rightSelectionStartX.toInt(),
                        (selectedHoursY - (selection_h) * topIndex).toInt()
                    )
                )
                topIndex--;
            } else if (i > selectedMills.toInt()) { // 下面的数字
                millsPoint.add(
                    Point(
                        rightSelectionStartX.toInt(),
                        (selectedHoursY + (selection_h) * bottomIndex).toInt()
                    )
                )
                bottomIndex++;
            } else {  // 选中的数字
                millsPoint.add(Point(rightSelectionStartX.toInt(), selectedHoursY.toInt()))
            }
        }
    }


    private fun initHoursPoint() {
        hoursPoints.clear()
        var topIndex = selectedNum.toInt()
        var bottomIndex = 1;
        var selectedHoursX = leftSelectionStartX + (selection_w / 2 - fontSize / 2)
        var selectedHoursY =
            leftSelectionStartY + (selection_h / 2 + fontSize / 2 - 5)

        for (i in 0..leftCount) {
            if (i < selectedNum.toInt()) { // 上面的数字
                hoursPoints.add(
                    Point(
                        selectedHoursX.toInt(),
                        (selectedHoursY - (selection_h) * topIndex).toInt()
                    )
                )
                topIndex--;
            } else if (i > selectedNum.toInt()) { // 下面的数字
                hoursPoints.add(
                    Point(
                        selectedHoursX.toInt(),
                        (selectedHoursY + (selection_h) * bottomIndex).toInt()
                    )
                )
                bottomIndex++;
            } else {  // 选中的数字
                hoursPoints.add(Point(selectedHoursX.toInt(), selectedHoursY.toInt()))
            }
        }
    }


    var leftSelectionStartX = 0f
    var leftSelectionStartY = 0f
    var leftSelectionEndX = 0f
    var rightSelectionStartX = 0f

    /**
     * 选中区域
     *
     * @param colonX 冒号的 x 坐标
     * @param colonY 冒号的 y 坐标
     */
    private fun drawSelectionLines(canvas: Canvas, colonX: Float, colonY: Float) {
        leftSelectionStartX = colonX - space - selection_w
        leftSelectionEndX = colonX - space

        leftSelectionStartY = measuredHeight / 2 - selection_h / 2
        var leftSelectionEndY = leftSelectionStartY;

        rightSelectionStartX = leftSelectionStartX + 2 * space + selection_w + 30f //30f 是冒号的宽度
        var rightSelectionEndX = rightSelectionStartX + selection_w;


        // left top line
        canvas.drawLine(
            leftSelectionStartX,
            leftSelectionStartY,
            leftSelectionEndX,
            leftSelectionEndY,
            linePaint
        )

        // right top line  30f 是冒号的宽度

        canvas.drawLine(
            rightSelectionStartX,
            leftSelectionStartY,
            rightSelectionEndX,
            leftSelectionEndY,
            linePaint
        )

        // left bottom line

        canvas.drawLine(
            leftSelectionStartX,
            leftSelectionStartY + selection_h,
            leftSelectionEndX,
            leftSelectionEndY + selection_h,
            linePaint
        )
        // right bottom line

        canvas.drawLine(
            rightSelectionStartX,
            leftSelectionStartY + selection_h,
            rightSelectionEndX,
            leftSelectionEndY + selection_h,
            linePaint
        )
    }


    /**
     * 绘制 小时 和秒
     *
     * @param colonX 冒号的 x 坐标
     * @param colonY 冒号的 y 坐标
     */
    private fun drawHoursAndMill(canvas: Canvas) {


        for (i in 0..leftCount) {
            if (model == 1) {
                selectedNum = preSelectHours;
            }

            if (i.toString() == selectedNum) {
                var selectedHoursX =
                    leftSelectionStartX + (selection_w / 2 - fontSize / 2) + offsetX
                var selectedHoursY =
                    leftSelectionStartY + (selection_h / 2 + fontSize / 2 - 5)
                canvas.drawText(
                    i.toString().clockNum(),
                    selectedHoursX,
                    selectedHoursY,
                    selectedPaint
                )
                if (selectedNum.toInt() != 0) {
                    canvas.drawText(
                        (selectedNum.toInt() - 1).toString().clockNum(),
                        selectedHoursX,
                        selectedHoursY - selection_h,
                        unselectedPaint
                    )
                }
                if (selectedNum.toInt() <= leftCount - 1) {
                    canvas.drawText(
                        (selectedNum.toInt() + 1).toString().clockNum(),
                        selectedHoursX,
                        selectedHoursY + selection_h,
                        unselectedPaint
                    )
                }
                preSelectHours = selectedNum;

            }
        }
        for (i in 0..rightCount) {
            if (model == 0) {
                selectedMills = preSelectMills;
            }
            if (i.toString() == selectedMills) {
                var selectedHoursX =
                    leftSelectionStartX + 2 * space + selection_w + selection_w / 3 + 30f + offsetX //30f 是冒号的宽度
                var selectedHoursY =
                    leftSelectionStartY + (selection_h / 2 + fontSize / 2 - 5)
                canvas.drawText(
                    i.toString().clockNum(),
                    selectedHoursX,
                    selectedHoursY,
                    selectedPaint
                )
                if (selectedMills.toInt() != 0) {
                    canvas.drawText(
                        (selectedMills.toInt() - 1).toString().clockNum(),
                        selectedHoursX,
                        selectedHoursY - selection_h,
                        unselectedPaint
                    )
                }
                if (selectedMills.toInt() <= rightCount - 1) {
                    canvas.drawText(
                        (selectedMills.toInt() + 1).toString().clockNum(),
                        selectedHoursX,
                        selectedHoursY + selection_h,
                        unselectedPaint
                    )
                }

                preSelectMills = selectedMills;
            }
        }

    }

    var startY = 0

    var endY = 0
    override fun onTouchEvent(event: MotionEvent?): Boolean {

        when (event?.action) {
            MotionEvent.ACTION_DOWN -> {
                startY = event.y.toInt();
                val startX = event.x
                if (startX <= leftSelectionEndX) {
                    model = 0
                } else if (startX >= rightSelectionStartX) {
                    model = 1;
                }
            }

            MotionEvent.ACTION_MOVE -> {
                endY = event.y.toInt()
                if (endY > startY) {
                    // 下滑
                    if ((model == 0 && selectedNum.toInt() == 0) || (model == 1 && selectedMills.toInt() == 0)) {
                        scrollDistance = 0F
                    } else {
                        scrollDistance = scrollDistanceValue
                    }


                } else if (endY < startY) {
                    //上划
                    if ((model == 0 && selectedNum.toInt() == leftCount) || (model == 1 && selectedMills.toInt() == rightCount)) {
                        scrollDistance = 0F
                    } else {
                        scrollDistance = -scrollDistanceValue
                    }


                }
                postDelayed({
                    checkSelectionNums();
                }, 100)
            }
        }
        return true;
    }


    /**
     * 判断选中的数字
     */
    private fun checkSelectionNums() {
        if (model == 0) {
            hoursPoints.onEachIndexed { index, it ->
                checkOutLine(it, index) {
                    if (this.timeScrollListener != null) {
                        this.timeScrollListener!!.scrollSelectedTimeFormat("${selectedNum.clockNum()} : ${selectedMills.clockNum()}")
                        this.timeScrollListener!!.scrollSelectedHours(
                            selectedNum.toInt(),
                            selectedNum.clockNum()
                        )

                    }
                    selectedNum = it
                    invalidate()
                }

            }
        } else if (model == 1) {
            millsPoint.onEachIndexed { index, it ->
                checkOutLine(it, index) {
                    selectedMills = it
                    if (this.timeScrollListener != null) {
                        this.timeScrollListener!!.scrollSelectedTimeFormat("${selectedNum.clockNum()} : ${selectedMills.clockNum()}")
                        this.timeScrollListener!!.scrollSelectedHours(
                            selectedMills.toInt(),
                            selectedMills.clockNum()
                        )
                    }
                    invalidate()
                }

            }
        }
    }


    /**
     * 越界判断
     */
    fun checkOutLine(point: Point, index: Int, callback: (selected: String) -> Unit) {
        point.y += scrollDistance.toInt()
        if (point.y >= leftSelectionStartY && point.y <= leftSelectionStartY + selection_h) {
            isStart = false
            callback(index.toString())
        }
    }

    /**
     *绘制中间的冒号
     */
    private fun drawColon(canvas: Canvas, colonX: Float, colonY: Float) {

        canvas.drawText(":", colonX, colonY, colonPaint)

    }


    fun String.clockNum(): String {
        if (!this.isDigitsOnly()) {
            return this
        }
        if (this.toInt() < 10) {
            return "0${this}"
        }

        return this;
    }


    public fun addTimerScrollListener(timeScrollListener: ITimerScrollListener) {
        this.timeScrollListener = timeScrollListener
    }


    public interface ITimerScrollListener {
        fun scrollSelectedHours(selectedHours: Int, selectedHoursFormat: String);
        fun scrollSelectedMinuter(selectedMinuter: Int, selectedMinuterFormat: String);

        fun scrollSelectedTimeFormat(time: String)
    }


    fun setSelectNums(selectedNums : String){
        this.selectedNum = selectedNums
        this.preSelectHours = selectedNums;
        invalidate()
    }

    fun getSelectedNum() : String{
        return this.selectedNum;
    }


    fun setSelectMills(selectedMills : String){
        this.selectedMills = selectedMills
        this.preSelectMills = selectedMills;
        invalidate()
    }

    fun getSelectedMills() : String{
        return this.selectedMills;
    }

}
